/*
 * =====================================================================================
 *
 *       Filename:  timer.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  01/26/2018 11:20:02 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (), 
 *   Organization:  
 *
 * =====================================================================================
 */
#include "timer.h"
using namespace std;

map<string,timer_t*> CTimer::m_ids;
unsigned int CTimer::m_sig = SIGRTMIN;

void CTimer::install_sig_handler(unsigned int sig,TimerHandler callback)
{
	struct sigaction sa;
	sa.sa_sigaction = callback;
	sa.sa_flags     = SA_SIGINFO;
	sigemptyset(&sa.sa_mask);
	sigaction(sig,  &sa, NULL);
}

void CTimer::sig_block(int sig)
{
    sigset_t mask;

    sigemptyset(&mask);
    sigaddset(&mask, sig);
    sigprocmask(SIG_SETMASK, &mask, NULL);
}

void CTimer::sig_unblock(int sig)
{
    sigset_t mask;

    sigemptyset(&mask);
    sigaddset(&mask, sig);
    sigprocmask(SIG_UNBLOCK, &mask, NULL);
}

bool CTimer::install_timer_handler(timer_t *ptid,unsigned long sec,
        TimerHandler callback,unsigned long usec)
{
    if (ptid == NULL)
        return false;
    
    int sig = m_sig++;
    if (m_sig > max_timer_sig)
        return false;

    install_sig_handler(sig,callback);
    
    struct sigevent evt;
    struct itimerspec spec;
    evt.sigev_notify = SIGEV_SIGNAL;
    evt.sigev_signo  = sig;
    evt.sigev_value.sival_ptr = ptid;
    
    if (timer_create(CLOCK_REALTIME,&evt,ptid) != 0)
        return false;
    // 剩余时间
    spec.it_value.tv_sec        = sec;
    spec.it_value.tv_nsec       = 0;
    // 时间间隔
    spec.it_interval.tv_sec     = sec;
    spec.it_interval.tv_nsec    = 0;
    
    // 启动timer
    if (timer_settime(*ptid,0,&spec,NULL) != 0)
        return false;
    
    return true;
}

bool CTimer::regTimer(const string& name,unsigned long sec,unsigned long nanosec,
            TimerHandler callback)
{
    timer_t* pt = new timer_t;
    bool bret = install_timer_handler(pt,sec,callback,nanosec);
    if (bret)
        m_ids[name] = pt;
    else
        delete pt;

    return bret;
}

timer_t* CTimer::getTimerId(const string& name)
{
    map<string,timer_t*>::iterator it = m_ids.find(name);
    if (it != m_ids.end())
        return it->second;

    return NULL;
}

void CTimer::clearTimers()
{
    map<string,timer_t*>::iterator it;
    for (it = m_ids.begin(); it != m_ids.end(); ++it)
    {
        timer_delete(it->second);
    }
    m_ids.clear();
}











